%{
#include <stdio.h>
#include <string.h>
#include <map>
#include <cstdio>
#include <iostream>
using namespace std;
extern "C" int yylex();
void yyerror(const char *s);
map<string, int> ids;
int checkIds(char*, char*);
%}

%token START
%token END
%token <size> INT
%token MOVE
%token TO
%token ADD
%token READ
%token PRINT
%token ENDLINE
%token STRING
%token COMMA
%token <id> IDENTIFIER
%token <num> NUMBER

%union {
    char* size;
    char* id;
    char* num;
}

%%

program: start middle end { printf("valid program"); }
;
start: START ENDLINE
;
end: END ENDLINE
;
middle: /* empty */
      | middle_lines 
;
middle_lines: middle_lines middle_line 
            | middle_line
;
middle_line: int_line
           | print_line
           | move_line
           | add_line
           | read_line
;
int_line: INT IDENTIFIER ENDLINE { 
	      printf("found int line: %s %s", $1, $2);
	      char* size = $1;
	      char* id = $2;

	      ids[id] = strlen(size);
	  }
;
print_line: PRINT print_statement
;
print_statement: print_statement COMMA IDENTIFIER
	       | print_statement COMMA STRING
	       | print_statement COMMA STRING ENDLINE { 
		     printf("found print line"); 
		 }
	       | print_statement COMMA IDENTIFIER ENDLINE { 
		     printf("found print line"); 
		 }
	       | IDENTIFIER
	       | STRING
               | IDENTIFIER ENDLINE { printf("found print line"); }
	       | STRING ENDLINE { printf("found print line"); }
;
move_line: MOVE IDENTIFIER TO IDENTIFIER ENDLINE { 
	       printf("found move line");

	       char* fromId = $2;
	       char* toId = $4;
 	       cout << " " << fromId << " " << toId; 
	       
	       if (!checkIds(fromId, toId)) {
	       }	  	       
	                
	   }
         | MOVE NUMBER TO IDENTIFIER ENDLINE { 
	       printf("found move line"); 

	       char* fromNum = $2;
	       char* toId = $4;
	       cout << " " << fromNum << " " << toId;

	       if (ids.count(toId) == 0) {
		   yyerror("the destination id does not exist"); 
	       }

	       if (strlen(fromNum) > ids.find(toId)->second) {
		   yyerror("the destination id is not big enough");
	       }
           }
;
add_line: ADD IDENTIFIER TO IDENTIFIER ENDLINE { printf("found add line"); }
        | ADD NUMBER TO IDENTIFIER ENDLINE { printf("found add line"); }
;
read_line: READ identifier_chain ENDLINE { printf("found read line"); }
;
identifier_chain: identifier_chain IDENTIFIER
                | IDENTIFIER
%%

extern FILE *yyin;

main() {
    do yyparse();
	while(!feof(yyin));
}

int checkIds(char* fromId, char* toId) {
	int fromSize = ids.find(fromId)->second;

	if (ids.count(fromId) == 0) {
		yyerror("the source id does not exist");
		return 0;
	}

	if (ids.count(toId) == 0) {
		yyerror("the destination id does not exist");
		return 0;
	}

	if (ids.find(toId)->second 
			< ids.find(fromId)->second) {
		yyerror("the destination is not large enough");
		return 0;
	}
    return 1;
}

void yyerror(const char *s) {
    fprintf(stderr, "%s\n", s);
}
